package com.kinoshita.common.jwt;

import com.fasterxml.jackson.databind.ObjectMapper;
import org.jose4j.jws.AlgorithmIdentifiers;
import org.jose4j.jws.JsonWebSignature;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.InvalidJwtException;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
import org.jose4j.lang.JoseException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.UnsupportedEncodingException;
import java.security.Key;

import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.jose4j.keys.HmacKey;


@Component
public class JwtTokenUtil {
    private static final String secret = "123456";
    private static final String ISSUER = "JEFF";
    private static Key key;

    static {
        try {
            key = new HmacKey(secret.getBytes("UTF-8"));
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }


    @Autowired
    private ObjectMapper objectMapper;

    // type: 0,user; 1,box; 2:cms
    public String getJWT(String id, String username, String roleCode) {
        JwtClaims claims = new JwtClaims();
        claims.setIssuer(ISSUER);
        claims.setClaim("userId", id);
        claims.setClaim("username", username);
        claims.setClaim("roleCode", roleCode);
        claims.setExpirationTimeMinutesInTheFuture(60 * 24 * 720);


        JsonWebSignature jws = new JsonWebSignature();
        jws.setPayload(claims.toJson());
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
        jws.setKey(key);
        jws.setDoKeyValidation(false); // relaxes the key length requirement

        String jwt = null;
        try {
            jwt = jws.getCompactSerialization();
        } catch (JoseException e) {
            // todo
            return null;
        }
        return jwt;
    }

    // type: 0,user; 1,box; 2:cms
    public String checkJWT(String token) {
        JwtConsumer jwtConsumer =
                new JwtConsumerBuilder()
                        .setRequireExpirationTime()
                        .setAllowedClockSkewInSeconds(30)
                        .setExpectedIssuer(ISSUER)
                        .setVerificationKey(key)
                        .setRelaxVerificationKeyValidation() // relaxes key length requirement
                        .build();

        JwtClaims processedClaims;
        try {
            processedClaims = jwtConsumer.processToClaims(token);
        } catch (InvalidJwtException e) {
            return null;
        }
        return (String) processedClaims.getClaimValue("userId");
    }

    public String getExternalJWT(String appKey, String appSecret) {
        JwtClaims claims = new JwtClaims();
        claims.setIssuer(ISSUER);
        //cms
        claims.setClaim("appKey", appKey);
        claims.setClaim("appSecret", appSecret);
        claims.setExpirationTimeMinutesInTheFuture(60 * 24 * 10);

        JsonWebSignature jws = new JsonWebSignature();
        jws.setPayload(claims.toJson());
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
        jws.setKey(key);
        jws.setDoKeyValidation(false); // relaxes the key length requirement

        String jwt = null;
        try {
            jwt = jws.getCompactSerialization();
        } catch (JoseException e) {
            // todo
            return null;
        }
        return jwt;
    }

    /**
     * 外部请求校验token
     * @param token
     * @return
     */
    public String checkExternalJWT(String token) {
        JwtConsumer jwtConsumer =
                new JwtConsumerBuilder()
                        .setRequireExpirationTime()
                        .setAllowedClockSkewInSeconds(30)
                        .setExpectedIssuer(ISSUER)
                        .setVerificationKey(key)
                        .setRelaxVerificationKeyValidation() // relaxes key length requirement
                        .build();

        JwtClaims processedClaims;
        try {
            processedClaims = jwtConsumer.processToClaims(token);
        } catch (InvalidJwtException e) {
            return null;
        }
        String id = processedClaims.getClaimValue("appKey") + " " + processedClaims
                .getClaimValue("appSecret");
        return id;
    }

    public String getUsername(String token) {
        JwtConsumer jwtConsumer = new JwtConsumerBuilder().setRequireExpirationTime()
                .setAllowedClockSkewInSeconds(30)
                .setExpectedIssuer(ISSUER)
                .setVerificationKey(key)
                .setRelaxVerificationKeyValidation() // relaxes key length requirement
                .build();
        JwtClaims jwtClaims;
        String userName;
        try {
            jwtClaims = jwtConsumer.processToClaims(token);
            userName = jwtClaims.getClaimValue("userName", String.class);
        } catch (Exception e) {
            return null;
        }
        return userName;
    }

    /**
     * 将map参数 JWT加密
     * @param clainmMap
     * @param minute 有效分钟数
     * @return
     */
    public String getJWTByMap(Map<String,Object> clainmMap,int minute) {
        JwtClaims claims = new JwtClaims();
        claims.setIssuer(ISSUER);
        for (Entry<String,Object> entry: clainmMap.entrySet()) {
            if(entry.getValue() != null){
                claims.setClaim(entry.getKey(), entry.getValue());
            }
        }
        claims.setExpirationTimeMinutesInTheFuture(minute);
        return getJWT(claims.toJson());
    }

    public Map<String,Object>  getMap(String token) {
        JwtConsumer jwtConsumer = new JwtConsumerBuilder().setRequireExpirationTime()
                .setAllowedClockSkewInSeconds(2)
                .setExpectedIssuer(ISSUER)
                .setVerificationKey(key)
                .setRelaxVerificationKeyValidation() // relaxes key length requirement
                .build();
        JwtClaims jwtClaims;
        Map<String, Object> claimsMap;
        try {
            jwtClaims = jwtConsumer.processToClaims(token);
            claimsMap = jwtClaims.getClaimsMap();
        } catch (Exception e) {
            return null;
        }
        return claimsMap;
    }

    private String getJWT(String claimsJsonString){
        JsonWebSignature jws = new JsonWebSignature();
        jws.setPayload(claimsJsonString);
        jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.HMAC_SHA256);
        jws.setKey(key);
        jws.setDoKeyValidation(false); // relaxes the key length requirement

        String jwt = null;
        try {
            jwt = jws.getCompactSerialization();
        } catch (JoseException e) {
            return null;
        }
        return jwt;
    }


}

